home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_400 / 424_01 / ed_157 / killer.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-09-11  |  15.1 KB  |  573 lines

  1. /*
  2.  * Copyright (C) 1992 by Rush Record (rhr@clio.rice.edu)
  3.  * 
  4.  * This file is part of ED.
  5.  * 
  6.  * ED is free software; you can redistribute it and/or modify it under the terms
  7.  * of the GNU General Public License as published by the Free Software Foundation.
  8.  * 
  9.  * ED is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
  10.  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
  11.  * PARTICULAR PURPOSE.  See the GNU General Public License for more details.
  12.  * 
  13.  * You should have received a copy of the GNU General Public License along with ED
  14.  * (see the file COPYING).  If not, write to the Free Software Foundation, 675
  15.  * Mass Ave, Cambridge, MA 02139, USA.
  16.  */
  17. #include "opsys.h"
  18.  
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21.  
  22. #include "memory.h"
  23. #include "rec.h"
  24. #include "window.h"
  25. #include "ed_dec.h"
  26. #include "buffer.h"
  27.  
  28. static Char copyonly = 0;
  29. static Char boxcut = 0;
  30.     
  31. /******************************************************************************\
  32. |Routine: copy_only
  33. |Callby: command edit output_file sort_recs
  34. |Purpose: Sets the copyonly flag, which makes the next kill operation not alter
  35. |         the buffer, but just copy the selection to the paste buffer.
  36. |Arguments:
  37. |    none
  38. \******************************************************************************/
  39. void copy_only(value)
  40. Int value;
  41. {
  42.     copyonly = value;
  43. }
  44.  
  45. /******************************************************************************\
  46. |Routine: killer_box
  47. |Callby: edit output_file sort_recs
  48. |Purpose: A one-shot to enable box cuts.
  49. |Arguments:
  50. |    none
  51. \******************************************************************************/
  52. void killer_box()
  53. {
  54.     boxcut = 1;
  55. }
  56.  
  57. /******************************************************************************\
  58. |Routine: killer
  59. |Callby: edit output_file sort_recs word_fill
  60. |Purpose: Handles deletion of text from buffers.
  61. |Arguments:
  62. |    offset is the offset from the current position to the other end of the
  63. |            text to be deleted.
  64. |    buffer is the buffer into which the deleted data is to be saved.
  65. |    append is a flag that causes the deleted data to be appended to the buffer,
  66. |            instead of replacing it entirely.
  67. \******************************************************************************/
  68. void killer(offset,buffer,append)
  69. Int offset;
  70. buf_ptr buffer;
  71. Int append;
  72. {
  73.     register rec_ptr otherrec,next,newbotrec;
  74.     rec_ptr rec,mergerec;
  75.     Int otherbyt,nrecs,frombottom,fromtop,fixeob,firstcol,lastcol,firstbyt,lastbyt,otherrow,boxmode;
  76.     register Int i;
  77.  
  78.     boxmode = boxcut;
  79.     boxcut = 0;
  80.     if(copyonly)
  81.     {
  82.         copyonly = 0;
  83.         copier(offset,buffer,append,boxmode);
  84.         return;
  85.     }
  86.     if(!offset && !boxmode)    /* if we are on the select range marker, and killing, handle specially */
  87.     {
  88.         if(append)    /* appending nothing does nothing */
  89.             return;
  90.         buffer_empty(buffer);    /* killing nothing only empties the buffer */
  91.         return;
  92.     }
  93.     if(offset <= 0)    /* we are deleting backwards from current position */
  94.     {
  95.         if(CURREC == BASE->next && !CURBYT && offset)    /* ignore backward kills at top of file */
  96.         {
  97.             abort_key();
  98.             return;
  99.         }
  100. /* check for some pathological things */
  101.         if(boxmode)
  102.         {
  103.              if(CURREC == BASE)
  104.             {
  105.                 if(CURREC->next == BASE)    /* box cut in empty buffer does nothing except to paste buffer */
  106.                 {
  107.                     if(append)    /* appending nothing does nothing */
  108.                         return;
  109.                     buffer_empty(buffer);    /* killing nothing only empties the buffer */
  110.                     return;
  111.                 }
  112.                 WANTCOL = 1;
  113.                 up_arrow(1);    /* move up to start of last record in buffer */
  114.                 offset += CURREC->length + 1;    /* offset is less negative, by the length of the last record, plus 1 for the newline */
  115.             }
  116.             fixeob = 0;            
  117.         }
  118.         else
  119.         {
  120. /* make a note of whether the EOB is likely to get wiped */
  121.             if(CURREC == BASE && !BOTREC)
  122.                 fixeob = 1;
  123.             else
  124.                 fixeob = 0;
  125.         }
  126. /* find the other end of the buffer, backwards */
  127.         otherrec = CURREC;
  128.         otherbyt = CURBYT;
  129.         otherrow = CURROW;
  130.         nrecs = 1;
  131.         while(offset++ < 0)
  132.         {
  133.             if(!otherbyt)
  134.             {
  135.                 if(otherrec->prev == BASE)
  136.                 {
  137.                     abort_key();
  138.                     return;
  139.                 }
  140.                 otherrec = otherrec->prev;
  141.                 otherbyt = otherrec->length;
  142.                 nrecs++;
  143.                 otherrow--;
  144.             }
  145.             else
  146.                 otherbyt--;
  147.         }
  148.         if(otherrow < TOPROW)
  149.             otherrow = TOPROW;
  150. /* if box cut in effect, get column range */
  151.         if(boxmode)
  152.         {
  153.             firstcol = get_column(CURREC,CURBYT);
  154.             lastcol = get_column(otherrec,otherbyt);
  155.             if(firstcol > lastcol)
  156.             {
  157.                 i = firstcol;
  158.                 firstcol = lastcol;
  159.                 lastcol = i;
  160.             }
  161.         }
  162. /* save records to buffer, if it was passed */
  163.         if(buffer != 0)
  164.         {
  165.             if(!append)
  166.                 buffer_empty(buffer);
  167.             else
  168.             {
  169.                 if(buffer->first == (rec_ptr)&buffer->first)    /* if the buffer is empty, forget about appending */
  170.                     append = 0;
  171.                 else
  172.                     mergerec = buffer->last;
  173.             }
  174.             if(boxmode)
  175.             {
  176.                 for(rec = otherrec;rec != CURREC->next;rec = rec->next)
  177.                 {
  178.                     firstbyt = get_colbyt(rec,firstcol);    /* get_colbyt must convert tabs to spaces, make record long enough, etc. */
  179.                     lastbyt = get_colbyt(rec,lastcol);
  180.                     buffer_append(buffer,rec,firstbyt,lastbyt + 1);
  181.                 }
  182.                 if(append)
  183.                     buffer->nrecs += nrecs;
  184.                 else
  185.                     buffer->nrecs = nrecs;
  186.             }
  187.             else
  188.             {
  189.                 if(otherrec == CURREC)
  190.                     buffer_append(buffer,CURREC,otherbyt,CURBYT);
  191.                 else
  192.                 {
  193.                     rec = otherrec;
  194.                     buffer_append(buffer,rec,otherbyt,rec->length);
  195.                     rec = rec->next;
  196.                     for(i = 1;i < nrecs - 1;i++)
  197.                     {
  198.                         buffer_append(buffer,rec,0,rec->length);
  199.                         rec = rec->next;
  200.                     }
  201.                     buffer_append(buffer,rec,0,CURBYT);
  202.                 }
  203.                 if(!append)
  204.                     buffer->nrecs = nrecs;
  205.                 else
  206.                 {
  207.                     buffer->nrecs += nrecs - 1;
  208.                     rec_merge(&mergerec);
  209.                 }
  210.             }
  211.             buffer->direction = -1;
  212.         }
  213. /* alter the record data structures and redisplay */
  214.         if(boxmode)
  215.         {
  216.             for(rec = otherrec,i = nrecs;i--;rec = rec->next)
  217.             {
  218.                 firstbyt = get_colbyt(rec,firstcol);
  219.                 lastbyt = get_colbyt(rec,lastcol);
  220.                 if(OVERSTRIKE)
  221.                     memset(rec->data + firstbyt,' ',lastbyt - firstbyt + 1);
  222.                 else
  223.                     rec_trim(&rec,firstbyt,lastbyt + 1);
  224.             }
  225.             CURREC = rec->prev;
  226.             paint(otherrow,CURROW,FIRSTCOL);
  227.             if((i = nrecs - 1))
  228.                 up_arrow(i);    /* move up to where select marker was */
  229.             CURBYT = get_colbyt(CURREC,firstcol - 1) + 1;    /* position to smallest of curcol, selcol */
  230.         }
  231.         else
  232.         {
  233.             if(nrecs == 1)
  234.             {
  235.                 if(OVERSTRIKE)
  236.                     memset(CURREC->data + otherbyt,' ',CURBYT - otherbyt);
  237.                 else
  238.                     rec_trim(&CURREC,otherbyt,CURBYT);    /* kill was entirely in current record */
  239.                 paint(CURROW,CURROW,FIRSTCOL);    /* repaint current record */
  240.                 CURBYT = otherbyt;
  241.             }
  242.             else
  243.             {
  244. /* figure out where lines scroll into view */
  245.                 if(!OVERSTRIKE)
  246.                 {
  247.                     for(NEWTOPREC = TOPREC,i = 1;NEWTOPREC->prev != BASE && i < nrecs;NEWTOPREC = NEWTOPREC->prev,i++);
  248.                     fromtop = i - 1;    /* how many we are able to get from the top */
  249.                     frombottom = nrecs - i;    /* how many we are not able to get from top, thus must get from bottom */
  250.                 }
  251. /* deal with the database */
  252.                 rec = otherrec;    /* don't use otherrec any more, rec_trim may change it */
  253.                 if(otherbyt != otherrec->length)
  254.                 {
  255.                     if(OVERSTRIKE)
  256.                         memset(rec->data + otherbyt,' ',otherrec->length - otherbyt);
  257.                     else
  258.                         rec_trim(&rec,otherbyt,otherrec->length);       /* trim the tail off the first record if necessary */
  259.                 }
  260.                 rec = rec->next;
  261.                 if(OVERSTRIKE)
  262.                     for(i = 1;i < nrecs - 1;i++)    /* blank out intervening records, if any */
  263.                     {
  264.                         memset(rec->data,' ',rec->length);
  265.                         rec = rec->next;
  266.                     }
  267.                 else
  268.                     for(i = 1;i < nrecs - 1;i++)    /* remove intervening records, if any */
  269.                     {
  270.                         next = rec->next;
  271.                         remq(rec);
  272.                         if(rec->recflags & 1)
  273.                             ifree(rec->data);
  274.                         ifree(rec);
  275.                         rec = next;
  276.                     }
  277.                 if(CURBYT != 0)
  278.                 {
  279.                     if(OVERSTRIKE)
  280.                         memset(rec->data,' ',CURBYT);
  281.                     else
  282.                         rec_trim(&rec,0,CURBYT);    /* trim the front off the last record if necessary */
  283.                 }
  284. /* fix the display */
  285.                 if(OVERSTRIKE)
  286.                 {
  287.                     paint(otherrow,CURROW,FIRSTCOL);
  288.                     CURREC = otherrec;
  289.                     CURBYT = otherbyt;
  290.                     CURROW = otherrow;
  291.                 }
  292.                 else
  293.                 {
  294.                     CURREC = rec->prev;
  295.                     rec_merge(&CURREC);    /* merge the two records */
  296.                     TOPREC = NEWTOPREC;
  297.                     if(fromtop > 0)
  298.                     {
  299.                         if(fromtop >= CURROW - TOPROW)    /* complete repaint from TOPROW to CURROW - 1 */
  300.                             paint(TOPROW,CURROW - 1,FIRSTCOL);
  301.                         else
  302.                         {
  303.                             marge(TOPROW,CURROW);
  304.                             move(TOPROW,1);
  305.                             ins_line(fromtop);
  306.                             paint(TOPROW,TOPROW + fromtop - 1,FIRSTCOL);
  307.                             marge(TOPROW,BOTROW);
  308.                         }
  309.                     }
  310.                     if(frombottom > 0)
  311.                     {
  312.                         CURROW -= frombottom;
  313.                         if(CURROW != TOPROW)
  314.                             marge(CURROW,BOTROW);
  315.                         move(CURROW,1);
  316.                         del_line(frombottom);
  317.                         if(CURROW != TOPROW)
  318.                             marge(TOPROW,BOTROW);
  319.                         move(BOTROW - frombottom + 1,1);
  320.                         paint(BOTROW - frombottom + 1,BOTROW,FIRSTCOL);
  321.                     }
  322.                     paint(CURROW,CURROW,FIRSTCOL);
  323.                     for(BOTREC = TOPREC,i = TOPROW;BOTREC != BASE && i < BOTROW;BOTREC = BOTREC->next,i++);
  324.                     if(i < BOTROW)
  325.                         BOTREC = 0;
  326.                     CURBYT = otherbyt;
  327.                 }
  328.             }
  329.         }
  330.     }
  331. /********************************************************************************/
  332. /********************************************************************************/
  333. /********************************************************************************/
  334.     else    /* we are deleting forwards from the current position */
  335.     {
  336.         if(CURREC == BASE)    /* ignore forward kills at end of file */
  337.         {
  338.             abort_key();
  339.             return;
  340.         }
  341. /* find the other end of the buffer, forwards */
  342.         otherrec = CURREC;
  343.         otherbyt = CURBYT;
  344.         otherrow = CURROW;
  345.         nrecs = 1;
  346.         while(offset-- > 0)
  347.         {
  348.             if(otherrec == BASE)
  349.             {
  350.                 abort_key();
  351.                 return;
  352.             }
  353.             if(otherbyt == otherrec->length)
  354.             {
  355.                 otherrec = otherrec->next;
  356.                 otherbyt = 0;
  357.                 otherrow++;
  358.                 nrecs++;
  359.             }
  360.             else
  361.                 otherbyt++;
  362.         }
  363.         if(otherrow > BOTROW)
  364.             otherrow = BOTROW;
  365. /* check for some pathological things */
  366.         if(boxmode)
  367.         {
  368.             fixeob = 0;            
  369.              if(otherrec == BASE)
  370.             {
  371.                 otherrec = otherrec->prev;
  372.                 otherbyt = 0;
  373.                 nrecs--;
  374.                 offset -= otherrec->length + 1;    /* offset is smaller, by the length of the last record, plus 1 for the newline */
  375.             }
  376.         }
  377.         else
  378.         {
  379. /* make a note of whether the EOB is likely to get wiped */
  380.             if(otherrec == BASE && !BOTREC)
  381.                 fixeob = 1;
  382.             else
  383.                 fixeob = 0;
  384.         }
  385. /* if box cut in effect, get column range */
  386.         if(boxmode)
  387.         {
  388.             firstcol = get_column(CURREC,CURBYT);
  389.             lastcol = get_column(otherrec,otherbyt);
  390.             if(firstcol > lastcol)
  391.             {
  392.                 i = firstcol;
  393.                 firstcol = lastcol;
  394.                 lastcol = i;
  395.             }
  396.         }
  397. /* save records to buffer, if it was passed */
  398.         if(buffer != 0)
  399.         {
  400.             if(!append)
  401.                 buffer_empty(buffer);
  402.             else
  403.             {
  404.                 if(buffer->first == (rec_ptr)&buffer->first)    /* if the buffer is empty, forget about appending */
  405.                     append = 0;
  406.                 else
  407.                     mergerec = buffer->last;
  408.             }
  409.             if(boxmode)
  410.             {
  411.                 for(rec = CURREC;rec != otherrec->next;rec = rec->next)
  412.                 {
  413.                     firstbyt = get_colbyt(rec,firstcol);    /* get_colbyt must convert tabs to spaces, make record long enough, etc. */
  414.                     lastbyt = get_colbyt(rec,lastcol);
  415.                     buffer_append(buffer,rec,firstbyt,lastbyt + 1);
  416.                 }
  417.                 if(append)
  418.                     buffer->nrecs += nrecs;
  419.                 else
  420.                     buffer->nrecs = nrecs;
  421.             }
  422.             else
  423.             {
  424.                 if(otherrec == CURREC)
  425.                     buffer_append(buffer,CURREC,CURBYT,otherbyt);
  426.                 else
  427.                 {
  428.                     buffer_append(buffer,CURREC,CURBYT,CURREC->length);
  429.                     rec = CURREC->next;
  430.                     for(i = 1;i < nrecs - 1;i++)
  431.                     {
  432.                         buffer_append(buffer,rec,0,rec->length);
  433.                         rec = rec->next;
  434.                     }
  435.                     buffer_append(buffer,rec,0,otherbyt);
  436.                 }
  437.                 if(!append)
  438.                     buffer->nrecs = nrecs;
  439.                 else
  440.                 {
  441.                     buffer->nrecs += nrecs - 1;
  442.                     rec_merge(&mergerec);
  443.                 }
  444.             }
  445.             buffer->direction = 1;
  446.         }
  447. /* alter the record data structures and redisplay */
  448.         if(boxmode)
  449.         {
  450.             for(rec = CURREC,i = nrecs;i--;rec = rec->next)
  451.             {
  452.                 firstbyt = get_colbyt(rec,firstcol);
  453.                 lastbyt = get_colbyt(rec,lastcol);
  454.                 if(OVERSTRIKE)
  455.                     memset(rec->data + firstbyt,' ',lastbyt - firstbyt + 1);
  456.                 else
  457.                     rec_trim(&rec,firstbyt,lastbyt + 1);
  458.             }
  459.             paint(CURROW,otherrow,FIRSTCOL);
  460.             CURBYT = get_colbyt(CURREC,firstcol - 1) + 1;    /* position to smallest of curcol, selcol */
  461.         }
  462.         else
  463.         {
  464.             if(nrecs == 1)
  465.             {
  466.                 if(OVERSTRIKE)
  467.                     memset(CURREC->data + CURBYT,' ',otherbyt - CURBYT);
  468.                 else
  469.                     rec_trim(&CURREC,CURBYT,otherbyt);    /* kill was entirely in current record */
  470.                 paint(CURROW,CURROW,FIRSTCOL);    /* repaint current record */
  471.             }
  472.             else
  473.             {
  474. /* figure out where lines scroll into view */
  475.                 if(!OVERSTRIKE)
  476.                 {
  477.                     for(newbotrec = BOTREC,i = 1;newbotrec != BASE && newbotrec != 0 && i < nrecs;newbotrec = newbotrec->next,i++);
  478.                     frombottom = i - 1;    /* how many we are able to get from the bottom */
  479.                     fromtop = nrecs - i;    /* how many we are not able to get from bottom, thus must get from top */
  480.                     for(NEWTOPREC = TOPREC,i = 0;NEWTOPREC->prev != BASE && i < fromtop;NEWTOPREC = NEWTOPREC->prev,i++);
  481.                     if((i = fromtop - i) > 0)
  482.                     {
  483.                         frombottom += i;    /* if top can't give us that many, get from bottom instead, leaving [eob] floating */
  484.                         fromtop -= i;    /* reduce acquisition from top */
  485.                     }
  486.                 }
  487. /* deal with the database */
  488.                 if(CURBYT != CURREC->length)
  489.                 {
  490.                     if(OVERSTRIKE)
  491.                         memset(CURREC->data + CURBYT,' ',CURREC->length - CURBYT);
  492.                     else
  493.                         rec_trim(&CURREC,CURBYT,CURREC->length);        /* trim the tail off the first record if necessary */
  494.                 }
  495.                 rec = CURREC->next;
  496.                 if(OVERSTRIKE)
  497.                     for(i = 1;i < nrecs - 1;i++)    /* blank out intervening records, if any */
  498.                     {
  499.                         memset(rec->data,' ',rec->length);
  500.                         rec = rec->next;
  501.                     }
  502.                 else
  503.                     for(i = 1;i < nrecs - 1;i++)    /* remove intervening records, if any */
  504.                     {
  505.                         next = rec->next;
  506.                         remq(rec);
  507.                         if(rec->recflags & 1)
  508.                             ifree(rec->data);
  509.                         ifree(rec);
  510.                         rec = next;
  511.                     }
  512.                 if(otherbyt != 0)
  513.                 {
  514.                     if(OVERSTRIKE)
  515.                         memset(rec->data,' ',otherbyt);
  516.                     else
  517.                         rec_trim(&rec,0,otherbyt);    /* trim the front off the last record if necessary */
  518.                 }
  519. /* fix the display */
  520.                 if(OVERSTRIKE)
  521.                     paint(CURROW,otherrow,FIRSTCOL);
  522.                 else
  523.                 {
  524.                     rec_merge(&CURREC);    /* merge the two records */
  525.                     TOPREC = NEWTOPREC;
  526.                     if(fromtop > 0)
  527.                     {
  528.                         if(CURROW + fromtop - 1 < BOTROW)
  529.                             marge(TOPROW,CURROW + fromtop - 1);
  530.                         move(TOPROW,1);
  531.                         ins_line(fromtop);
  532.                         paint(TOPROW,TOPROW + fromtop - 1,FIRSTCOL);
  533.                         if(CURROW + fromtop - 1 < BOTROW)
  534.                             marge(TOPROW,BOTROW);
  535.                         CURROW += fromtop;
  536.                     }
  537.                     if(frombottom > 0)
  538.                     {
  539.                         if(frombottom >= BOTROW - CURROW)    /* complete repaint from CURROW + 1 to BOTROW */
  540.                             paint(CURROW + 1,BOTROW,FIRSTCOL);
  541.                         else
  542.                         {
  543.                             if(CURROW != TOPROW)
  544.                                 marge(CURROW,BOTROW);
  545.                             move(CURROW,1);
  546.                             del_line(frombottom);
  547.                             if(CURROW != TOPROW)
  548.                                 marge(TOPROW,BOTROW);
  549.                             move(BOTROW - frombottom + 1,1);
  550.                             paint(BOTROW - frombottom + 1,BOTROW,FIRSTCOL);
  551.                         }
  552.                     }
  553.                     paint(CURROW,CURROW,FIRSTCOL);
  554.                     for(BOTREC = TOPREC,i = TOPROW;BOTREC != BASE && i < BOTROW;BOTREC = BOTREC->next,i++);
  555.                     if(i < BOTROW)
  556.                         BOTREC = 0;
  557.                 }
  558.             }
  559.         }
  560.     }
  561. /* insure that EOB is there if it is above the bottom */
  562.     if(fixeob)
  563.     {
  564.         for(rec = TOPREC,i = TOPROW;rec != BASE;rec = rec->next,i++);
  565.         move(i,1);
  566.         eob();
  567.     }
  568. /* establish new location and column context */
  569.     fix_scroll();
  570.     return;
  571. }
  572.  
  573.